
package com.sapuo.enroll.filter;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;

/**
 * 
 * @author huangzhen 日志记录过滤器
 *
 */

@WebFilter(urlPatterns = { "/mobile/*"})
@Slf4j
public class LogRecordFilter implements Filter {
	/**
	 * 消息显示最大长度
	 */
	public static final int MAX_LENTH = 1000;

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		ObjectMapper om = new ObjectMapper();
		ObjectNode logRecord = om.createObjectNode();
		long start = System.currentTimeMillis();
		try {
			HttpServletRequest httpRequest = (HttpServletRequest) request;
			HttpServletResponse httpResponse = (HttpServletResponse) response;
			ContentCachingRequestWrapper cachingRequest = new ContentCachingRequestWrapper(httpRequest);
			ContentCachingResponseWrapper cachingResponse = new ContentCachingResponseWrapper(httpResponse);

			chain.doFilter(cachingRequest, cachingResponse);
//			判断请求是否来做swagger，如果是则跳过日志输出
			String referer = null==httpRequest.getHeader("Referer")?"":httpRequest.getHeader("Referer");
			if (!referer.endsWith("swagger-ui.html")){
				Enumeration<String> headNames = httpRequest.getHeaderNames();
				while (headNames.hasMoreElements()) {
					String headName = headNames.nextElement();
					logRecord.put(headName, httpRequest.getHeader(headName));
				}
				logRecord.put("ReqRemoteAddr", httpRequest.getRemoteAddr());
				logRecord.put("ReqTime",new Date().toString());
				logRecord.put("ReqMethod", httpRequest.getMethod());
				logRecord.put("ReqURL", httpRequest.getRequestURL().toString());
				logRecord.put("ReqQueryString", httpRequest.getQueryString());
				try {
					JsonNode node = om.readTree(cachingRequest.getContentAsByteArray());
					logRecord.set("ReqParam",node);
				} catch (Exception e) {
//				log.error(e.getMessage(),e);
					logRecord.put("ReqParam", new String(cachingRequest.getContentAsByteArray()));
				}

				logRecord.put("RespStatus", cachingResponse.getStatus());
				logRecord.put("RespContentsize", cachingResponse.getContentSize());
				if (cachingResponse.getContentSize() > MAX_LENTH) {
					logRecord.put("RespContent", new String(cachingResponse.getContentAsByteArray(), 0, 999));
				} else {
//				logRecord.put("RespContent", JSONObject.parse(cachingResponse.getContentAsByteArray()));
					JsonNode node = om.readTree(cachingResponse.getContentAsByteArray());
					logRecord.set("RespContent", node);
				}
				ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
						.getRequestAttributes();
				Throwable exception = (Throwable) requestAttributes.getAttribute(
						String.format("%s.ERROR", DefaultErrorAttributes.class.getName()), RequestAttributes.SCOPE_REQUEST);
//				if (null != exception) {
					logRecord.put("RespContentsize",
							null != exception.getMessage() ? exception.getMessage().getBytes().length : 0);
					logRecord.put("RespContent", exception.getMessage());

//				}
				logRecord.put("TimeCost", String.format("%sms", System.currentTimeMillis() - start));
				log.info(logRecord.toString());
			}

			cachingResponse.copyBodyToResponse();
		} catch (Exception e) {
			log.error("filter exception,request content:{}", logRecord.toString(), e);
		}

	}

	@Override
	public void destroy() {

	}

}
